package cn.wolfcode.rbac.filter;

import cn.wolfcode.rbac.domain.LoginUser;
import cn.wolfcode.rbac.util.JWTUtils;
import cn.wolfcode.rbac.util.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        // 请求进入放行2个接口url
        String uri = httpServletRequest.getRequestURI();
        if (uri.startsWith("/api/tokens") || uri.startsWith("/api/verifyCodes")){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }
        // jwt检查
        String jwtToken = httpServletRequest.getHeader("token");
        // 有中文，设置编码
        httpServletResponse.setContentType("application/json;charset=utf-8");
        // 把对象转成json字符串，或者把json字符串转对象
        ObjectMapper mapper = new ObjectMapper();
        if (!StringUtils.hasText(jwtToken)){
            httpServletResponse.getWriter().write(
                    mapper.writeValueAsString(R.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(),"登陆令牌必须传"))
            );
            return;
        }

        if (!JWTUtils.isExpired(jwtToken)){
            httpServletResponse.getWriter().write(
                    mapper.writeValueAsString(R.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(),"登陆令牌不合法或者失效"))
            );
            return;
        }

        // 进行认证--将jwt转换成用户登录主体，方便后续接口获取当前当前登录用户信息

        String username = JWTUtils.getToken(jwtToken, "login_user_name");
        LoginUser details = (LoginUser) userDetailsService.loadUserByUsername(username);
        if (details == null){
            // 抛出异常
            httpServletResponse.getWriter().write(
                    mapper.writeValueAsString(R.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "登陆令牌校验失效,请重新登陆"))
            );
        }

        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                details.getUsername(),
                details.getPassword(),
                details.getAuthorities()
        );
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        filterChain.doFilter(httpServletRequest,httpServletResponse);
    }
}
